﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using IDT.Entity;
using Image = System.Drawing.Image;
using System.Threading;
using IDT.Downloader;

namespace IDT.Wpf.Watcher
{
    /// <summary>
    /// Interaction logic for DownloadImageWindow.xaml
    /// </summary>
    public partial class DownloadImageWindow : Window
    {
        public DownloadType DownloadType { get; set; }

        public CategoryCollection Categories { get; set; }

        public Category Category { get; set; }

        public Album Album { get; set; }

        public Photo Photo { get; set; }

        public DirectoryInfo Directory { get; set; }

        public ImageDownloader ImageDownloader { get; set; }

        public DownloadImageWindow(DownloadType downloadType, DirectoryInfo directory , CategoryCollection categories, ImageDownloader imageDownloader) :this(downloadType, directory, imageDownloader)
        {
            Categories = categories;
        }

        public DownloadImageWindow(DownloadType downloadType, DirectoryInfo directory, Category category, ImageDownloader imageDownloader) : this(downloadType, directory, imageDownloader)
        {
            Category = category;
        }

        public DownloadImageWindow(DownloadType downloadType, DirectoryInfo directory, Album album, ImageDownloader imageDownloader) : this(downloadType, directory, imageDownloader)
        {
            Album = album;
        }

        public DownloadImageWindow(DownloadType downloadType, DirectoryInfo directory, Photo photo, ImageDownloader imageDownloader) : this(downloadType, directory, imageDownloader)
        {
            Photo = photo;
        }

        private DownloadImageWindow(DownloadType downloadType, DirectoryInfo directory, ImageDownloader imageDownloader) : this()
        {
            DownloadType = downloadType;
            Directory = directory;
            ImageDownloader = imageDownloader;
        }

        public DownloadImageWindow()
        {
            InitializeComponent();
            ListBoxAlbums.ItemsSource = DownloadedAlbums;
            ListBoxImages.ItemsSource = DownloadedImages;
            cancellationTokenSource = new CancellationTokenSource();
            cancellationToken = cancellationTokenSource.Token;

        }

        public ObservableCollection<Album> DownloadedAlbums { get; } = new ObservableCollection<Album>();

        public ObservableCollection<Photo> DownloadedImages { get; } = new ObservableCollection<Photo>();

        private CancellationTokenSource cancellationTokenSource = null;

        private CancellationToken cancellationToken = CancellationToken.None;

        private void DoWindowLoaded(object sender, RoutedEventArgs e)
        {
            if (DownloadType == DownloadType.Category)
            {
                TextBoxDownloadAlbumFromIndex.Visibility = Visibility.Visible;
                TextBoxDownloadAlbumCount.Visibility = Visibility.Visible;
            }
        }

        private async Task DownloadWebsite(CategoryCollection categories)
        {
            if (categories != null)
            {
                foreach (Category category in categories)
                {
                    await DownloadCategory(category);
                }
            }
        }

        private async Task DownloadCategory(Category category)
        {
            if (category != null)
            {
                ProgressBarAlbumsDownloaded.Maximum = category.Albums.Count;
                ProgressBarAlbumsDownloaded.Value = 0;

                int skippedCount = 0;
                int.TryParse(TextBoxDownloadAlbumFromIndex.Text.Trim(), out skippedCount);
                int downloadCount = category.Albums.Count - skippedCount;
                int.TryParse(TextBoxDownloadAlbumCount.Text.Trim(), out downloadCount);

                if (DownloadType != DownloadType.Category)
                {
                    skippedCount = 0;
                    downloadCount = category.Albums.Count;
                }

                foreach (Album album in category.Albums.Skip(skippedCount).Take(downloadCount))
                {
                    await DownloadAlbum(album);
                    ListBoxAlbums.SelectedIndex = ListBoxAlbums.Items.Count - 1;
                    ListBoxAlbums.ScrollIntoView(ListBoxAlbums.SelectedItem);
                    ProgressBarAlbumsDownloaded.Value++;
                }
            }
        }

        private async Task DownloadAlbum(Album album)
        {
            if (album != null)
            {
                await DownloadImage(album.AlbumCover);

                if (album.Photos == null || album.Photos.Count == 0)
                {
                    album.Photos = await ImageDownloader.GetPhotosForAlbum(album);
                }

                ProgressBarImagessDownloaded.Maximum = album.Photos.Count;
                ProgressBarImagessDownloaded.Value = 0;

                foreach (Photo photo in album.Photos)
                {
                    
                    await DownloadImage(photo);

                    DownloadedImages.Add(photo);
                    ListBoxImages.SelectedIndex = ListBoxImages.Items.Count - 1;
                    ListBoxImages.ScrollIntoView(ListBoxImages.SelectedItem);
                    ProgressBarImagessDownloaded.Value++;
                }

                DownloadedAlbums.Add(album);
            }
        }


        private async Task DownloadImage(Photo image)
        {
            if (image != null)
            {
                await Task.Run(() =>
                {
                    try
                    {
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            string directoryString =
                                $"{Directory.FullName}\\{image.Album.Category.Name}\\{image.Album.AlbumId:D5}_{image.Album.Name}";
                            DirectoryInfo directory = new DirectoryInfo(directoryString);

                            if (!directory.Exists)
                            {
                                directory.Create();
                            }

                            string imagePath = $"{directoryString}\\{image.Name}";
                            if (!File.Exists(imagePath))
                            {
                                HttpWebRequest request = WebRequest.CreateHttp(image.Url) as HttpWebRequest;
                                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                                {
                                    Image imageToSave = Image.FromStream(response.GetResponseStream());
                                    imageToSave.Save(imagePath);
                                }
                            }
                        }
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }, cancellationToken);
            }
        }

        private void DoButtonCloseClicked(object sender, RoutedEventArgs e)
        {
            cancellationTokenSource.Cancel(false);
            Close();
        }

        private async void DoButtonStartClicked(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            button.IsEnabled = false;
            TextBoxDownloadAlbumFromIndex.IsEnabled = false;
            switch (DownloadType)
            {
                case DownloadType.Website:
                    await DownloadWebsite(Categories);
                    break;
                case DownloadType.Category:
                    await DownloadCategory(Category);
                    break;
                case DownloadType.Album:
                    ProgressBarAlbumsDownloaded.Maximum = 1;
                    await DownloadAlbum(Album);
                    break;
                case DownloadType.Image:
                    ProgressBarImagessDownloaded.Maximum = 1;
                    await DownloadImage(Photo);
                    break;
            }
        }

        private void DoButtonClearClicked(object sender, RoutedEventArgs e)
        {
            DownloadedAlbums.Clear();
            DownloadedImages.Clear();
        }
    }
}
